"""Task List Component - Custom Task Item Widget.

This module provides widgets for displaying individual download tasks and a list of tasks.
"""

from PySide6.QtCore import Signal
from PySide6.QtWidgets import (
    QHBoxLayout,
    QLabel,
    QProgressBar,
    QPushButton,
    QVBoxLayout,
    QWidget,
)

from ..models.task import DownloadTask, TaskStatus


class TaskItemWidget(QWidget):
    """A custom widget for displaying a single download task item.

    This widget shows task details like title, status, progress, speed, and file size,
    along with action buttons (pause, resume, cancel, delete).
    """

    # 信号定义
    pause_clicked = Signal(str)  # task_id
    resume_clicked = Signal(str)
    cancel_clicked = Signal(str)
    delete_clicked = Signal(str)

    def __init__(self, task: DownloadTask, parent: QWidget | None = None):
        """Initializes the TaskItemWidget.

        Args:
            task: The download task associated with this widget.
            parent: The parent widget, defaults to None.
        """
        super().__init__(parent)
        self.task = task
        self.init_ui()

    def init_ui(self) -> None:
        """Initializes the user interface components of the task item widget,
        including labels for title, status, speed, and size, a progress bar, and action buttons.
        """
        layout = QVBoxLayout()
        layout.setContentsMargins(10, 5, 10, 5)

        # === 第一行：标题和状态 ===
        title_layout = QHBoxLayout()

        # 标题
        self.title_label = QLabel(self.task.title)
        self.title_label.setStyleSheet("font-weight: bold; font-size: 14px;")
        title_layout.addWidget(self.title_label)

        title_layout.addStretch()

        # 状态标签
        self.status_label = QLabel(self.task.status.value)
        self.status_label.setStyleSheet(self._get_status_style(self.task.status))
        title_layout.addWidget(self.status_label)

        layout.addLayout(title_layout)

        # === 第二行：进度条 ===
        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setValue(int(self.task.progress))
        self.progress_bar.setTextVisible(True)
        self.progress_bar.setFormat(f"{self.task.progress:.1f}%")
        layout.addWidget(self.progress_bar)

        # === 第三行：详细信息 ===
        info_layout = QHBoxLayout()

        # 速度
        self.speed_label = QLabel(self._format_speed(self.task.speed))
        self.speed_label.setStyleSheet("color: #666;")
        info_layout.addWidget(self.speed_label)

        # 文件大小
        if self.task.file_size:
            size_label = QLabel(f"大小: {self._format_size(self.task.file_size)}")
            size_label.setStyleSheet("color: #666;")
            info_layout.addWidget(size_label)

        info_layout.addStretch()

        # 操作按钮
        button_layout = QHBoxLayout()

        if self.task.status == TaskStatus.DOWNLOADING:
            pause_btn = QPushButton("暂停")
            pause_btn.clicked.connect(lambda: self.pause_clicked.emit(self.task.id))
            button_layout.addWidget(pause_btn)

        elif self.task.status in (TaskStatus.PAUSED, TaskStatus.FAILED):
            resume_btn = QPushButton("恢复")
            resume_btn.clicked.connect(lambda: self.resume_clicked.emit(self.task.id))
            button_layout.addWidget(resume_btn)

        if self.task.status != TaskStatus.COMPLETED:
            cancel_btn = QPushButton("取消")
            cancel_btn.clicked.connect(lambda: self.cancel_clicked.emit(self.task.id))
            button_layout.addWidget(cancel_btn)

        delete_btn = QPushButton("删除")
        delete_btn.clicked.connect(lambda: self.delete_clicked.emit(self.task.id))
        button_layout.addWidget(delete_btn)

        info_layout.addLayout(button_layout)
        layout.addLayout(info_layout)

        self.setLayout(layout)

        # 样式
        self.setStyleSheet(
            """
            QWidget {
                background-color: white;
                border: 1px solid #ddd;
                border-radius: 5px;
            }
            QWidget:hover {
                border: 1px solid #aaa;
            }
            QPushButton {
                padding: 5px 15px;
                border: 1px solid #ccc;
                border-radius: 3px;
                background-color: #f5f5f5;
            }
            QPushButton:hover {
                background-color: #e0e0e0;
            }
        """
        )

    def update_task(self, task: DownloadTask) -> None:
        """Updates the display of the task item widget with new task data.

        Args:
            task: The updated download task object.
        """
        self.task = task

        # 更新标题
        self.title_label.setText(task.title)

        # 更新状态
        self.status_label.setText(task.status.value)
        self.status_label.setStyleSheet(self._get_status_style(task.status))

        # 更新进度
        self.progress_bar.setValue(int(task.progress))
        self.progress_bar.setFormat(f"{task.progress:.1f}%")

        # 更新速度
        self.speed_label.setText(self._format_speed(task.speed))

    @staticmethod
    def _get_status_style(status: TaskStatus) -> str:
        """Returns a CSS style string based on the task status.

        Args:
            status: The current status of the task.

        Returns:
            A CSS style string for the status label.
        """
        color_map = {
            TaskStatus.PENDING: "#FFA500",  # 橙色
            TaskStatus.DOWNLOADING: "#1E90FF",  # 蓝色
            TaskStatus.PAUSED: "#FFD700",  # 金色
            TaskStatus.COMPLETED: "#32CD32",  # 绿色
            TaskStatus.FAILED: "#DC143C",  # 红色
            TaskStatus.CANCELLED: "#808080",  # 灰色
        }

        color = color_map.get(status, "#000000")
        return f"color: {color}; font-weight: bold; padding: 3px 8px; border-radius: 3px;"

    @staticmethod
    def _format_speed(bytes_per_sec: float) -> str:
        """Formats a given speed in bytes per second into a human-readable string (e.g., KB/s, MB/s).

        Args:
            bytes_per_sec: The speed in bytes per second.

        Returns:
            A formatted string representing the speed.
        """
        if bytes_per_sec == 0:
            return "速度: --"

        mb_per_sec = bytes_per_sec / 1024 / 1024
        if mb_per_sec >= 1:
            return f"速度: {mb_per_sec:.2f} MB/s"
        else:
            kb_per_sec = bytes_per_sec / 1024
            return f"速度: {kb_per_sec:.2f} KB/s"

    @staticmethod
    def _format_size(bytes_size: int) -> str:
        """Formats a given size in bytes into a human-readable string (e.g., KB, MB, GB).

        Args:
            bytes_size: The size in bytes.

        Returns:
            A formatted string representing the size.
        """
        units = ["B", "KB", "MB", "GB", "TB"]
        size = float(bytes_size)
        unit_index = 0

        while size >= 1024 and unit_index < len(units) - 1:
            size /= 1024
            unit_index += 1

        return f"{size:.2f} {units[unit_index]}"


class TaskListWidget(QWidget):
    """A widget that displays a list of download tasks.

    This widget dynamically adds and removes `TaskItemWidget` instances
    to represent each download task, providing a scrollable view of all active downloads.
    """

    # 信号定义
    task_action = Signal(str, str)  # action, task_id

    def __init__(self, parent: QWidget | None = None):
        """Initializes the TaskListWidget.

        Args:
            parent: The parent widget, defaults to None.
        """
        super().__init__(parent)
        self.task_widgets: dict[str, TaskItemWidget] = {}
        self.init_ui()

    def init_ui(self) -> None:
        """Initializes the user interface components of the task list widget."""
        self.layout = QVBoxLayout()
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(5)
        self.layout.addStretch()
        self.setLayout(self.layout)

    def add_task(self, task: DownloadTask) -> None:
        """Adds a new task to the list.

        Args:
            task: The download task to add.
        """
        if task.id in self.task_widgets:
            # 更新现有任务
            self.update_task(task)
            return

        # 创建新的任务项
        task_widget = TaskItemWidget(task)

        # 连接信号
        task_widget.pause_clicked.connect(lambda tid: self.task_action.emit("pause", tid))
        task_widget.resume_clicked.connect(lambda tid: self.task_action.emit("resume", tid))
        task_widget.cancel_clicked.connect(lambda tid: self.task_action.emit("cancel", tid))
        task_widget.delete_clicked.connect(lambda tid: self.task_action.emit("delete", tid))

        # 添加到布局（在stretch之前）
        self.layout.insertWidget(self.layout.count() - 1, task_widget)
        self.task_widgets[task.id] = task_widget

    def update_task(self, task: DownloadTask) -> None:
        """Updates an existing task's display.

        Args:
            task: The updated task object.
        """
        if task.id in self.task_widgets:
            self.task_widgets[task.id].update_task(task)

    def remove_task(self, task_id: str) -> None:
        """Removes a task from the list by its ID.

        Args:
            task_id: The ID of the task to remove.
        """
        if task_id in self.task_widgets:
            widget = self.task_widgets.pop(task_id)
            self.layout.removeWidget(widget)
            widget.deleteLater()

    def clear_tasks(self) -> None:
        """Clears all tasks from the list.
        """
        for task_id in list(self.task_widgets.keys()):
            self.remove_task(task_id)

    def get_task_widget(self, task_id: str) -> TaskItemWidget | None:
        """Retrieves a TaskItemWidget by its task ID.

        Args:
            task_id: The ID of the task widget to retrieve.

        Returns:
            The TaskItemWidget if found, otherwise None.
        """
        return self.task_widgets.get(task_id)

    def get_task_count(self) -> int:
        """Returns the number of tasks currently in the list.

        Returns:
            The total number of tasks.
        """
        return len(self.task_widgets)
